
module frv_isq_entry (
    input                       clk             ,
    input                       rst_n           ,
    input                       pd_rst          ,
    //Entry Control
    // input                       isqe_flush      , 
    // input [5:0]     isqe_flush_id   , 
    output                      isqe_valid      ,
    output                      isqe_ready      , //when Operation Num is valid, this can be pull up
    //Entry Data
    input                       isqe_wreq       , // Issue Queue Request
    input [5:0]     isq_inst_id     , // Issue Queue Request
    input [31:0]                isq_inst_data   ,
    input                       isq_exp_vld     ,
    input [4:0]                 isq_exp_code    ,
    input [31:0]                isq_pc_data     ,
    //ALU Control Interface
    input                       isq_alu_vld     ,
    input                       isq_alu_land    ,
    input                       isq_alu_lor     ,
    input                       isq_alu_lxor    ,
    input                       isq_alu_sll     ,
    input                       isq_alu_srl     ,
    input                       isq_alu_sra     ,
    input                       isq_alu_add     ,
    input                       isq_alu_sub     ,
    input                       isq_alu_slt     ,
    input                       isq_alu_unsign  ,
    //Branch Control Interface
    input                       isq_bru_vld     ,
    input                       isq_bru_beq     ,
    input                       isq_bru_bne     ,
    input                       isq_bru_blt     ,
    input                       isq_bru_bge     ,
    input                       isq_bru_jal     ,
    input                       isq_bru_jalr    ,
    input [31:0]                isq_bp_taddr    , // bp target addr
    input                       isq_bp_taken    , // bp taken
    input [3:0]                 isq_bp_bhtv     , // BHT Entry Value
    input [31:0]                isq_bp_phtv     , // PHT Entry Value
    //LSU Control Interface
    input                       isq_lsu_vld     ,
    input                       isq_lsu_unsign  ,
    input                       isq_lsu_load    ,
    input                       isq_lsu_store   ,
    input                       isq_lsu_word    ,
    input                       isq_lsu_half    ,
    input                       isq_lsu_byte    ,
    //MDU Control Interface
    //TODO
    //CSR Control Interface
    input                       isq_csr_vld     ,
    input                       isq_csr_write   ,
    input                       isq_csr_set     ,
    input                       isq_csr_clr     , // CSR Clear
    //Operation number Interface
    input                       isq_rs1_vld     ,
    input                       isq_rs1_rdy     ,    
    input[5:0]      isq_rs1_ind     ,
    input                       isq_rs2_vld     ,
    input                       isq_rs2_rdy     ,    
    input[5:0]      isq_rs2_ind     ,
    input [31:0]                isq_rs1_val     ,
    input [31:0]                isq_rs2_val     ,
    input                       isq_imm_vld     ,
    input [31:0]                isq_imm_data    , // here we can compress the width
    input                       isq_rd_vld      ,
    // input [5:0]     isq_rd_ind      ,
    // input [5:0]     isq_rdm_ind     ,
    input                       isq_pc_used     , // jal and auipc will use the pc value        
    // ==========================================================================
    //ALU Interface 
    output                      alue_req        ,
    input                       alue_issue      ,
    output                      alue_ctrl_land  ,
    output                      alue_ctrl_lor   ,
    output                      alue_ctrl_lxor  ,
    output                      alue_ctrl_sll   ,
    output                      alue_ctrl_srl   ,
    output                      alue_ctrl_sra   ,
    output                      alue_ctrl_add   ,
    output                      alue_ctrl_sub   ,
    output                      alue_ctrl_slt   ,
    output                      alue_ctrl_unsign,
    output [5:0]    alue_inst_id    , // Instruction ID                   
    // ALU operation 
    output [31:0]               alue_op1_val    ,
    output [31:0]               alue_op2_val    ,
    // output [5:0]                alue_rd_ind     ,
    // ALU fwd
    input                       alu_fwd_vld     ,
    input  [31:0]               alu_fwd_val     ,    
    input  [5:0]    alu_fwd_inst_id  ,    
    // ==========================================================================
    //BRU Interface
    output                      brue_req        ,
    input                       brue_issue      ,    
    output                      brue_ctrl_beq   ,
    output                      brue_ctrl_bne   ,
    output                      brue_ctrl_blt   ,
    output                      brue_ctrl_bge   ,
    output                      brue_ctrl_jal   ,
    output                      brue_ctrl_jalr  ,
    output [5:0]    brue_inst_id    , // Instruction ID  
    //BRU Operation Num
    output [31:0]               brue_pc_data    ,
    output [31:0]               brue_op1_val    ,
    output [31:0]               brue_op2_val    ,
    output [31:0]               brue_imm_val    ,
    // output [5:0]                brue_rd_ind     ,
    output                      brue_rd_vld     ,
    output [31:0]               brue_bp_taddr   , // bp target addr
    output                      brue_bp_taken   , // bp taken
    output [3:0]                brue_bp_bhtv    , // BHT Entry Value
    output [31:0]               brue_bp_phtv    , // PHT Entry Value  
    //BRU Foward Interface
    input                       bru_fwd_vld     ,
    input  [5:0]    bru_fwd_inst_id ,
    input                       bru_fwd_rd_vld  ,
    input                       bru_flush       ,
    input  [31:0]               bru_fwd_val     ,          
    //LSU Interface                             
    output                      lsue_req        ,
    input                       lsue_issue      ,
    output                      lsue_ctrl_unsign,
    output                      lsue_ctrl_load  ,
    output                      lsue_ctrl_store ,
    output                      lsue_ctrl_word  ,
    output                      lsue_ctrl_half  ,
    output                      lsue_ctrl_byte  ,
    output [5:0]    lsue_inst_id    , // Instruction ID  
    //LSU Operation Number
    output [31:0]               lsue_op1_val    ,
    output [31:0]               lsue_op2_val    ,    
    output [31:0]               lsue_store_data ,

    input  [5:0]    lsu_fwd_inst_id ,
    input                       lsu_fwd_vld     ,
    input                       lsu_fwd_rd_vld  ,
    input  [31:0]               lsu_fwd_val      //rd value    

);

//Entry Content
wire                       entry_vld,entry_vld_nxt;
wire [5:0]     entry_inst_id   ; // Issue Queue Request
wire [31:0]                entry_inst_data ;
wire                       entry_exp_vld   ;
wire [4:0]                 entry_exp_code  ;
wire [31:0]                entry_pc_data   ;
//ALU Control Interface
wire                       entry_alu_vld   ;
wire                       entry_alu_land  ;
wire                       entry_alu_lor   ;
wire                       entry_alu_lxor  ;
wire                       entry_alu_sll   ;
wire                       entry_alu_srl   ;
wire                       entry_alu_sra   ;
wire                       entry_alu_add   ;
wire                       entry_alu_sub   ;
wire                       entry_alu_slt   ;
wire                       entry_alu_unsign;
//Branch Control Interface
wire                       entry_bru_vld   ;
wire                       entry_bru_beq   ;
wire                       entry_bru_bne   ;
wire                       entry_bru_blt   ;
wire                       entry_bru_bge   ;
wire                       entry_bru_jal   ;
wire                       entry_bru_jalr  ;
wire [31:0]                entry_bp_taddr  ; // bp target addr
wire                       entry_bp_taken  ; // bp taken
wire [3:0]                 entry_bp_bhtv   ; // BHT Entry Value
wire [31:0]                entry_bp_phtv   ; // PHT Entry Value
//LSU Control Interface
wire                       entry_lsu_vld   ;
wire                       entry_lsu_unsign;
wire                       entry_lsu_load  ;
wire                       entry_lsu_store ;
wire                       entry_lsu_word  ;
wire                       entry_lsu_half  ;
wire                       entry_lsu_byte  ;
//MDU Control Interface
//TODO
//CSR Control Interface
wire                       entry_csr_vld   ;
wire                       entry_csr_write ;
wire                       entry_csr_set   ;
wire                       entry_csr_clr   ; // CSR Clear
    //Operation number Interface
wire                       entry_rs1_vld   ;
wire                       entry_rs1_rdy   ;    
wire[5:0]      entry_rs1_ind   ;
wire                       entry_rs2_vld   ;
wire                       entry_rs2_rdy   ;    
wire[5:0]      entry_rs2_ind   ;
wire [31:0]                entry_rs1_val   ;
wire [31:0]                entry_rs2_val   ;
wire                       entry_imm_vld   ;
wire [31:0]                entry_imm_data  ; // here we can compress the width
wire                       entry_rd_vld    ;
wire [5:0]     entry_rd_ind    ;
// wire [5:0]     entry_rdm_ind   ;
wire                       entry_pc_used   ; // jal and auipc will use the pc value      
//Entry write enable
wire                       entry_wen;
//Operation Number
wire                       rs1_used_nrdy;
wire                       rs1_alu_match;
wire                       rs1_bru_match;
wire                       rs1_lsu_match;
wire                       rs1_fwd_match;

wire                       rs2_used_nrdy;
wire                       rs2_alu_match;
wire                       rs2_bru_match;
wire                       rs2_lsu_match;
wire                       rs2_fwd_match;

wire                       entry_rs1_rdy_nxt;    
wire [31:0]                entry_rs1_val_nxt;
wire                       entry_rs1_rdy_wen;    
wire                       entry_rs1_val_wen;
wire                       entry_rs2_rdy_nxt;    
wire [31:0]                entry_rs2_val_nxt;
wire                       entry_rs2_rdy_wen;    
wire                       entry_rs2_val_wen;

//Entry FLush
wire   entry_flush;
wire   entry_issue;
wire   entry_vld_wen;
wire   flush_inst_age_older;

//Entry Write Request
assign entry_wen = isqe_wreq;

//Forward Match

assign rs1_used_nrdy = entry_vld && entry_rs1_vld && ~entry_rs1_rdy;
assign rs1_alu_match = rs1_used_nrdy && alu_fwd_inst_id == entry_rs1_ind && alu_fwd_vld ;
assign rs1_bru_match = rs1_used_nrdy && bru_fwd_inst_id == entry_rs1_ind && bru_fwd_vld && bru_fwd_rd_vld;
assign rs1_lsu_match = rs1_used_nrdy && lsu_fwd_inst_id == entry_rs1_ind && lsu_fwd_vld && lsu_fwd_rd_vld;

assign rs1_fwd_match = rs1_alu_match | rs1_bru_match | rs1_lsu_match;

assign entry_rs1_val_nxt = ({32{rs1_alu_match}} & alu_fwd_val) |
                           ({32{rs1_bru_match}} & bru_fwd_val) |
                           ({32{rs1_lsu_match}} & lsu_fwd_val) | 
                           ({32{isqe_wreq}}     & isq_rs1_val)  
                           ;

assign entry_rs1_val_wen = rs1_fwd_match || isqe_wreq;

assign entry_rs1_rdy_nxt = isq_rs1_rdy || rs1_fwd_match;
assign entry_rs1_rdy_wen = rs1_fwd_match || isqe_wreq;

assign rs2_used_nrdy = entry_vld && entry_rs2_vld && ~entry_rs2_rdy;
assign rs2_alu_match = rs2_used_nrdy && alu_fwd_inst_id == entry_rs2_ind && alu_fwd_vld ;
assign rs2_bru_match = rs2_used_nrdy && bru_fwd_inst_id == entry_rs2_ind && bru_fwd_vld && bru_fwd_rd_vld;
assign rs2_lsu_match = rs2_used_nrdy && lsu_fwd_inst_id == entry_rs2_ind && lsu_fwd_vld && lsu_fwd_rd_vld;

assign rs2_fwd_match = rs2_alu_match | rs2_bru_match | rs2_lsu_match;
                         
assign entry_rs2_val_nxt = ({32{rs2_alu_match}} & alu_fwd_val) |
                           ({32{rs2_bru_match}} & bru_fwd_val) |
                           ({32{rs2_lsu_match}} & lsu_fwd_val) | 
                           ({32{isqe_wreq}}     & isq_rs2_val)  
                           ;

assign entry_rs2_val_wen = rs2_fwd_match || isqe_wreq;

assign entry_rs2_rdy_nxt = isq_rs2_rdy || rs2_fwd_match;
assign entry_rs2_rdy_wen = rs2_fwd_match || isqe_wreq;

//Entry FLush
wire br_flush_en;

rob_id_cmpo #(5+1) _rob_id_cmpo(bru_fwd_inst_id,entry_inst_id,flush_inst_age_older);
assign br_flush_en = bru_flush && flush_inst_age_older;
assign entry_flush = entry_vld && br_flush_en;

assign entry_issue = alue_issue || brue_issue || lsue_issue;

assign entry_vld_wen = entry_wen || entry_issue || entry_flush; 
assign entry_vld_nxt = ~entry_flush && entry_wen && ~entry_issue;

//Entry Information Support
wire   entry_rdy;

assign entry_rdy = (entry_rs1_rdy || ~entry_rs1_vld) &&
                   (entry_rs2_rdy || ~entry_rs2_vld) &&
                   entry_vld && ~br_flush_en;

assign isqe_ready = entry_rdy;
assign isqe_valid = entry_vld;

    //ALU Infor
assign alue_req = entry_rdy && entry_alu_vld;

assign alue_ctrl_land       = entry_alu_land   ;
assign alue_ctrl_lor        = entry_alu_lor    ;
assign alue_ctrl_lxor       = entry_alu_lxor   ;
assign alue_ctrl_sll        = entry_alu_sll    ;
assign alue_ctrl_srl        = entry_alu_srl    ;
assign alue_ctrl_sra        = entry_alu_sra    ;
assign alue_ctrl_add        = entry_alu_add    ;
assign alue_ctrl_sub        = entry_alu_sub    ;
assign alue_ctrl_slt        = entry_alu_slt    ;
assign alue_ctrl_unsign     = entry_alu_unsign ;
assign alue_inst_id         = entry_inst_id; // Instruction ID                   

assign alue_op1_val         = ({32{entry_rs1_vld}} & entry_rs1_val) |
                              ({32{entry_pc_used}} & entry_pc_data)
                              ;


assign alue_op2_val         = ({32{entry_rs2_vld}} & entry_rs2_val) |
                              ({32{~entry_rs2_vld}} & entry_imm_data)
                              ;

    //BRU Infor
assign brue_req = entry_rdy && entry_bru_vld;

assign brue_ctrl_beq        = entry_bru_beq  ;
assign brue_ctrl_bne        = entry_bru_bne  ;
assign brue_ctrl_blt        = entry_bru_blt  ;
assign brue_ctrl_bge        = entry_bru_bge  ;
assign brue_ctrl_jal        = entry_bru_jal  ;
assign brue_ctrl_jalr       = entry_bru_jalr ;
assign brue_inst_id         = entry_inst_id  ; // Instruction ID  
assign brue_rd_vld          = entry_rd_vld   ;
assign brue_bp_taddr        = entry_bp_taddr ; // bp target addr
assign brue_bp_taken        = entry_bp_taken ; // bp taken
assign brue_bp_bhtv         = entry_bp_bhtv  ; // BHT Entry Value
assign brue_bp_phtv         = entry_bp_phtv  ; // PHT Entry Value  

assign brue_pc_data         = entry_pc_data  ;
assign brue_imm_val         = entry_imm_data  ;
assign brue_op1_val         = entry_rs1_val  ;
assign brue_op2_val         = entry_rs2_val  ;

    //LSU Infor
assign lsue_req = entry_rdy && entry_lsu_vld;

assign lsue_ctrl_unsign    = entry_lsu_unsign;
assign lsue_ctrl_load      = entry_lsu_load  ;
assign lsue_ctrl_store     = entry_lsu_store ;
assign lsue_ctrl_word      = entry_lsu_word  ;
assign lsue_ctrl_half      = entry_lsu_half  ;
assign lsue_ctrl_byte      = entry_lsu_byte  ;
assign lsue_inst_id        = entry_inst_id   ; // Instruction ID  

assign lsue_op1_val        = entry_rs1_val   ;
assign lsue_op2_val        = entry_imm_data  ;

assign lsue_store_data     = entry_rs2_val   ;

//DFFs
//Entry Content
dffr #(1)                   entry_vld_ff       (clk,rst_n,entry_vld_wen,entry_vld_nxt,entry_vld);
dffr #(5+1)     entry_inst_id_ff   (clk,rst_n,entry_wen,isq_inst_id   ,entry_inst_id   ); 
dffr #(32)                  entry_inst_data_ff (clk,rst_n,entry_wen,isq_inst_data ,entry_inst_data );
dffr #(1)                   entry_exp_vld_ff   (clk,rst_n,entry_wen,isq_exp_vld   ,entry_exp_vld   );
dffr #(5)                   entry_exp_code_ff  (clk,rst_n,entry_wen,isq_exp_code  ,entry_exp_code  );
dffr #(32)                  entry_pc_data_ff   (clk,rst_n,entry_wen,isq_pc_data   ,entry_pc_data   );
dffr #(1)                   entry_alu_vld_ff   (clk,rst_n,entry_wen,isq_alu_vld   ,entry_alu_vld   );
dffr #(1)                   entry_alu_land_ff  (clk,rst_n,entry_wen,isq_alu_land  ,entry_alu_land  );
dffr #(1)                   entry_alu_lor_ff   (clk,rst_n,entry_wen,isq_alu_lor   ,entry_alu_lor   );
dffr #(1)                   entry_alu_lxor_ff  (clk,rst_n,entry_wen,isq_alu_lxor  ,entry_alu_lxor  );
dffr #(1)                   entry_alu_sll_ff   (clk,rst_n,entry_wen,isq_alu_sll   ,entry_alu_sll   );
dffr #(1)                   entry_alu_srl_ff   (clk,rst_n,entry_wen,isq_alu_srl   ,entry_alu_srl   );
dffr #(1)                   entry_alu_sra_ff   (clk,rst_n,entry_wen,isq_alu_sra   ,entry_alu_sra   );
dffr #(1)                   entry_alu_add_ff   (clk,rst_n,entry_wen,isq_alu_add   ,entry_alu_add   );
dffr #(1)                   entry_alu_sub_ff   (clk,rst_n,entry_wen,isq_alu_sub   ,entry_alu_sub   );
dffr #(1)                   entry_alu_slt_ff   (clk,rst_n,entry_wen,isq_alu_slt   ,entry_alu_slt   );
dffr #(1)                   entry_alu_unsign_ff(clk,rst_n,entry_wen,isq_alu_unsign,entry_alu_unsign);
dffr #(1)                   entry_bru_vld_ff   (clk,rst_n,entry_wen,isq_bru_vld   ,entry_bru_vld   );
dffr #(1)                   entry_bru_beq_ff   (clk,rst_n,entry_wen,isq_bru_beq   ,entry_bru_beq   );
dffr #(1)                   entry_bru_bne_ff   (clk,rst_n,entry_wen,isq_bru_bne   ,entry_bru_bne   );
dffr #(1)                   entry_bru_blt_ff   (clk,rst_n,entry_wen,isq_bru_blt   ,entry_bru_blt   );
dffr #(1)                   entry_bru_bge_ff   (clk,rst_n,entry_wen,isq_bru_bge   ,entry_bru_bge   );
dffr #(1)                   entry_bru_jal_ff   (clk,rst_n,entry_wen,isq_bru_jal   ,entry_bru_jal   );
dffr #(1)                   entry_bru_jalr_ff  (clk,rst_n,entry_wen,isq_bru_jalr  ,entry_bru_jalr  );
dffr #(32)                  entry_bp_taddr_ff  (clk,rst_n,entry_wen,isq_bp_taddr  ,entry_bp_taddr  ); // bp target addr
dffr #(1)                   entry_bp_taken_ff  (clk,rst_n,entry_wen,isq_bp_taken  ,entry_bp_taken  ); // bp taken
dffr #(4)                   entry_bp_bhtv_ff   (clk,rst_n,entry_wen,isq_bp_bhtv   ,entry_bp_bhtv   ); // BHT Entry Value
dffr #(32)                  entry_bp_phtv_ff   (clk,rst_n,entry_wen,isq_bp_phtv   ,entry_bp_phtv   ); // PHT Entry Value
dffr #(1)                   entry_lsu_vld_ff   (clk,rst_n,entry_wen,isq_lsu_vld   ,entry_lsu_vld   );
dffr #(1)                   entry_lsu_unsign_ff(clk,rst_n,entry_wen,isq_lsu_unsign,entry_lsu_unsign);
dffr #(1)                   entry_lsu_load_ff  (clk,rst_n,entry_wen,isq_lsu_load  ,entry_lsu_load  );
dffr #(1)                   entry_lsu_store_ff (clk,rst_n,entry_wen,isq_lsu_store ,entry_lsu_store );
dffr #(1)                   entry_lsu_word_ff  (clk,rst_n,entry_wen,isq_lsu_word  ,entry_lsu_word  );
dffr #(1)                   entry_lsu_half_ff  (clk,rst_n,entry_wen,isq_lsu_half  ,entry_lsu_half  );
dffr #(1)                   entry_lsu_byte_ff  (clk,rst_n,entry_wen,isq_lsu_byte  ,entry_lsu_byte  );
dffr #(1)                   entry_csr_vld_ff   (clk,rst_n,entry_wen,isq_csr_vld   ,entry_csr_vld   );
dffr #(1)                   entry_csr_write_ff (clk,rst_n,entry_wen,isq_csr_write ,entry_csr_write );
dffr #(1)                   entry_csr_set_ff   (clk,rst_n,entry_wen,isq_csr_set   ,entry_csr_set   );
dffr #(1)                   entry_csr_clr_ff   (clk,rst_n,entry_wen,isq_csr_clr   ,entry_csr_clr   ); // CSR Clear
dffr #(1)                   entry_rs1_vld_ff   (clk,rst_n,entry_wen,isq_rs1_vld   ,entry_rs1_vld   );
dffr #(1)                   entry_rs1_rdy_ff   (clk,rst_n,entry_rs1_rdy_wen,entry_rs1_rdy_nxt   ,entry_rs1_rdy   );    
dffr #(32)                  entry_rs1_val_ff   (clk,rst_n,entry_rs1_val_wen,entry_rs1_val_nxt   ,entry_rs1_val   );
dffr #(5+1)     entry_rs1_ind_ff   (clk,rst_n,entry_wen,isq_rs1_ind   ,entry_rs1_ind   );
dffr #(1)                   entry_rs2_vld_ff   (clk,rst_n,entry_wen,isq_rs2_vld   ,entry_rs2_vld   );
dffr #(1)                   entry_rs2_rdy_ff   (clk,rst_n,entry_rs2_rdy_wen,entry_rs2_rdy_nxt   ,entry_rs2_rdy   );    
dffr #(32)                  entry_rs2_val_ff   (clk,rst_n,entry_rs2_val_wen,entry_rs2_val_nxt   ,entry_rs2_val   );
dffr #(5+1)     entry_rs2_ind_ff   (clk,rst_n,entry_wen,isq_rs2_ind   ,entry_rs2_ind   );
dffr #(1)                   entry_imm_vld_ff   (clk,rst_n,entry_wen,isq_imm_vld   ,entry_imm_vld   );
dffr #(32)                  entry_imm_data_ff  (clk,rst_n,entry_wen,isq_imm_data  ,entry_imm_data  ); // here we can compress the width
dffr #(1)                   entry_rd_vld_ff    (clk,rst_n,entry_wen,isq_rd_vld    ,entry_rd_vld    );
// dffr #(5+1)     entry_rdm_ind_ff   (clk,rst_n,entry_wen,isq_rdm_ind   ,entry_rdm_ind   );
dffr #(1)                   entry_pc_used_ff   (clk,rst_n,entry_wen,isq_pc_used   ,entry_pc_used   ); // jal and auipc will use the pc value   


endmodule



